/**
 * @author JGY
 * @since 2024/1
 */
import { wsApi } from '@app-cad/server/wsApi';
import { Matrix4, Object3D } from 'three-legacy';

import { Transform, Types, pickedModelData, Matrix3x4 } from '@amcax/base';
import { ctx2 } from '@app-cad/module';

/**
 * 模型变换方法实例对象
 */
export class TransformerSingleton {
  private static _instance: TransformerSingleton;

  public static getInstance(): TransformerSingleton {
    if (!this._instance) {
      this._instance = new TransformerSingleton();
    }
    return this._instance;
  }

  modelsObj: Set<any>;
  shapeDxids: Set<string>;
  modelData: pickedModelData;
  sceneSetup;

  constructor() {
    this.init();
  }

  init() {
    this.modelsObj = new Set();
    this.shapeDxids = new Set();
    this.modelData = null;
    this.sceneSetup = ctx2.viewer.sceneSetup;
  }

  clear() {
    for (const model of this.modelsObj) {
      model.assisModel?.destroy();
    }
    this.modelsObj.clear();
    this.shapeDxids.clear();
  }

  setModels(modelData: pickedModelData) {
    if (!modelData) return;
    this.modelData = modelData;
    if (modelData.objInfo.type === Types.HOLE) {
      this.modelsObj.add(modelData.assisObj);
    } else {
      this.modelsObj.add(modelData.assisObj);
      this.modelsObj.add(modelData.originModel.edge);
      this.modelsObj.add(modelData.originModel.mesh);
      this.modelsObj.add(modelData.originModel.pickSceneEdge);
      this.modelsObj.add(modelData.originModel.pickSceneMesh);
    }
  }

  apply(matrix: Matrix4) {
    for (const model of this.modelsObj) {
      // if (model.type === 'Line') { // 消隐线模板对象
      //   model.applyMatrix4(matrix);
      // } else {
      // model.transferByMatrix4(matrix);
      // }
      model.transferByMatrix4(matrix);
    }
  }

  applyGroupBoxs(groupBoxs: Map<string, Object3D>, matrix: Matrix4) {
    if (!groupBoxs || !matrix) return;

    for (const box of groupBoxs) {
      box[1].applyMatrix4(matrix);
    }
  }

  doTransform(modelDataMap: Map<string, pickedModelData>, matrix: Matrix4) {
    if (!modelDataMap || !matrix) return;

    for (const modelInfo of modelDataMap) {
      this.shapeDxids.add(modelInfo[0]);
      this.setModels(modelInfo[1]);
    }
    // 处理消隐线
    // if (Intersecter().isIntersect) {
    //   for (const obj of Intersecter().assisLinesMap) {
    //     for (const dxid of this.shapeDxids) {
    //       if (dxid === obj[0]) {
    //         for (let i = 0, l = obj[1].length; i < l; i++) {
    //           this.modelsObj.add(obj[1][i])
    //           // if (obj[1][i].type === 'Line') { // 消隐线模板对象
    //           //   obj[1][i].visible = false;
    //           // } else {
    //           //   obj[1][i].visible = false;
    //           // }
    //         }
    //       }
    //     }
    //   }
    // }
    this.apply(matrix);
    ctx2.viewer.requestRender();
  }

  async commit(matrix = new Matrix4()) {
    // let newCsys = this.modelData.csys.clone();
    // newCsys.applyMatrix4(matrix);
    // // 更新placement
    // let placement = newCsys.getPlacement()
    // DataManager().updatePlacement(this.modelData.idInfo, placement);
    // this.sceneSetup.updatePickSenceTexture();
    // 提交transform
    const transform = Transform.matrixToTransform(
      new Matrix3x4().setFromMatrix4(matrix),
    );
    const shapeDxids = [];
    for (const id of this.shapeDxids) {
      shapeDxids.push(id);
    }
    if (transform && shapeDxids.length > 0) {
      await wsApi.setTransform({
        o: shapeDxids,
        transform: transform,
      });
    }
    this.clear();
    // ctx.cmdManager.execute(new ChaosTransaction());
    ctx2.viewer.requestRender();
  }

  exit() {
    this.clear();
    TransformerSingleton._instance = null;
  }
}

export const Transformer = () => {
  return TransformerSingleton.getInstance();
};
